﻿using Microsoft.Office.Interop.Excel;
using SUNRPA.CONTROLS.IMPL.domain;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using SUNRPA.CONTROLS.IMPL.domain.flowItemParam;
using SUNRPA.CONTROLS.IMPL.domain.flowRunningVar;
using SUNRPA.CONTROLS.IMPL.util;
using System.Collections.Concurrent;
using ExcelRange = Microsoft.Office.Interop.Excel.Range; 

namespace SUNRPA.CONTROLS.IMPL.controls {
    /// <summary>
    /// </summary>
    public class LoopExcelNAction:BaseControlActions {
        public override int Execute(int currentIndex, FlowItem item, ConcurrentDictionary<string, ConcurrentDictionary<string, RPAVariableDefineWrapper>> globleData, List<FlowItem> flowItems) {
            LoopExcelNParam? param = item.ControlParam as LoopExcelNParam;
            string loopObject = param.LoopObject;
            Workbook wb = this.GetObjVar<ExcelModel>(ref loopObject, globleData).WorkBookValue as Workbook;
            if(wb == null) { 
                throw new RpaRuntimeException(String.Format("Excel对象{0}不存在", loopObject));
            }

            ExcelUtil excelUtil = new ExcelUtil();
            excelUtil.SetApp(wb);

            int loopType = param.LoopType;

            string startRow = param.StartRow;
            string endRow = param.EndRow;
            string startColumn = param.StartColumn;
            string endColumn = param.EndColumn;
            this.GetStringVar(ref startRow, globleData);
            this.GetStringVar(ref endRow, globleData);
            this.GetStringVar(ref startColumn, globleData);
            this.GetStringVar(ref endColumn, globleData);
            
            string sheetName = param.SheetName;
            this.GetStringVar(ref sheetName, globleData);

            int startRowIndex = excelUtil.GetRowNum(startRow, sheetName);
            int startColumnIndex = excelUtil.GetColumnNum(startColumn, sheetName);
            int endRowIndex = excelUtil.GetRowNum(endRow, sheetName);
            int endColumnIndex = excelUtil.GetColumnNum(endColumn, sheetName);


            string loopItemOut = param.LoopItemOut;
            string loopIndexOut = param.LoopIndexOut;

            bool readShowContent = param.ReadShowsContent;
            bool trimContent = param.TrimContent;

            ExcelRange range;

            switch(loopType){ 
                case 0:
                    //已使用区域
                    range = excelUtil.GetRange(sheetName);
                    break;
                case 1:
                    //区域
                    range = excelUtil.GetRange(sheetName,startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
                    break;
                case 2:
                    //行
                    int lastColumn = excelUtil.GetColumnNum("-1", sheetName);
                    range = excelUtil.GetRange(sheetName,startRowIndex, 1, endRowIndex, lastColumn);
                    break;
                case 3:
                    //列
                    int lastRow = excelUtil.GetRowNum("-1", sheetName);
                    range = excelUtil.GetRange(sheetName,1, startColumnIndex, lastRow, endColumnIndex);
                    break;
                default:
                    range = excelUtil.GetRange(sheetName);
                    break;
            }
            if(loopType == 3) {
                for(int i = 1; i <= range.Columns.Count; i++) { 
                    List<object> content = new List<object>();
                    for(int j = 1; j <= range.Rows.Count; j++) { 
                        ExcelRange cell = range.Cells[j, i] as ExcelRange;
                        if(readShowContent) {
                            object text = cell.Text;
                            if(trimContent && text != null) { 
                                text = text.ToString().Trim();
                            }
                            content.Add(text);
                        } else { 
                            content.Add(cell.Value);
                        }
                    }
                    this.saveVar(globleData, loopItemOut, new ListModel<object>(loopItemOut, content), DefaultContents.RUNNING_PARAM);
                    this.saveVar(globleData, loopIndexOut, new IntModel(loopIndexOut, i), DefaultContents.RUNNING_PARAM);
                    //顺序执行定义在循环中的流程项
                    for(int k = currentIndex + 1; k < item.EndTag.Index; k++) {
                        BaseControlActions.updateInfoDelegate(k);
                        k = ExecuteAction(flowItems[k], globleData, flowItems);
                    }
                }
            } else { 
                for(int i = 1; i <= range.Rows.Count; i++) { 
                    List<object> content = new List<object>();
                    for(int j = 1; j <= range.Columns.Count; j++) { 
                        ExcelRange cell = range.Cells[i, j] as ExcelRange;
                        if(readShowContent) {
                            object text = cell.Text;
                            if(trimContent && text != null) { 
                                text = text.ToString().Trim();
                            }
                            content.Add(text);
                        } else { 
                            content.Add(cell.Value);
                        }
                    }
                    this.saveVar(globleData, loopItemOut, new ListModel<object>(loopItemOut, content), DefaultContents.RUNNING_PARAM);
                    this.saveVar(globleData, loopIndexOut, new IntModel(loopIndexOut, i), DefaultContents.RUNNING_PARAM);
                    //顺序执行定义在循环中的流程项
                    for(int k = currentIndex + 1; k < item.EndTag.Index; k++) {
                        BaseControlActions.updateInfoDelegate(k);
                        k = ExecuteAction(flowItems[k], globleData, flowItems);
                    }
                }
            }
            return item.EndTag.Index;
        }
    }
}
